/*
 * UDom_Server.cpp
 *
 *  Created on: 26.08.2014
 *      Author: Dave
 */

#include "UDom_Server.h"


UDom_Server::UDom_Server(Prngd_State state)
{

	create_socket = 0;
	new_socket = 0;
	size = 0;
	addrlen = 0;
	prngd = new Prngd(state);

	switch(state)
	{
		case TCP_ST:
			break;
		case UDP_ST:
			break;
		case DM_ST:
			this->port = port;
			StartWorkerThread();
			break;
		case MQ_ST:
			break;
		default:
			break;
	}

}


void UDom_Server::thread_listen(pthread_t parent_th)
{
	char buffer[BUFFER_SIZE];
	int size;
	worker_busy = false;
	memset(buffer, 0, BUFFER_SIZE);

	new_socket = accept( create_socket, (struct sockaddr*)&address, &addrlen);
		std::cout << "Client verbunden\n";

	while((size = recv(new_socket, buffer, BUFFER_SIZE, 0)) >0 || worker_busy)
	{

		if(!worker_busy)
		{
			if(strcmp(buffer, "/exit") == 0)
			{
				active = false;
				pthread_kill(parent_th, SIGUSR2);
			}
			else
			{
				worker_busy = true;
				strncpy(work_buffer, buffer, BUFFER_SIZE);
				std::cout << "\n Sende SIGUSR1 an worker";
				pthread_kill(parent_th, SIGUSR1);
			}
			memset(buffer, ' ', BUFFER_SIZE);
		}
		else
		{
			//meldung an client das server noch beschaeftigt
		}
	}
	close(new_socket);
	pthread_kill(parent_th, SIGPOLL);
}


void UDom_Server::thread_work()
{
	bool listen_thread_active = false;
	bool work_thread_active = true;
	char* temp = NULL;
	char* temp2 = NULL;
	active = true;

	char** array;

	if((create_socket=socket(AF_UNIX, SOCK_STREAM,0)) > 0)
		std::cout <<" Uds Socket wurde angelegt.\n";

	unlink(UDS_FILE);
	address.sun_family = AF_UNIX;
	strcpy(address.sun_path, UDS_FILE);

	if(bind(create_socket, (struct sockaddr*)&address, sizeof(address)) != 0)
		std::cout <<" Port ist nicht frei !\n";

	listen(create_socket, 5);
	addrlen = sizeof(struct sockaddr_in);


	sigfillset(&sigmask);
	pthread_sigmask(SIG_UNBLOCK, &sigmask, (sigset_t*)0);

	action.sa_flags = 0;
	action.sa_handler = dummy_handler;
	sigaction(SIGUSR1, &action, (struct sigaction*)0);
	sigaction(SIGUSR2, &action, (struct sigaction*)0);
	sigaction(SIGPOLL, &action, (struct sigaction*)0);

	while(work_thread_active)
	{
		param_count = 0;
		temp = NULL;
		temp2 = NULL;

		StartListenerThread((pthread_t)pthread_self());
		listen_thread_active= true;

		while(listen_thread_active)
		{
			sigwait(&sigmask, &sig);
			switch(sig)
			{
				case SIGUSR1:

					std::cout << "\nBufferinhalt: ";
					for(int i = 0; i < BUFFER_SIZE; i++)
					{
						std::cout << work_buffer[i];
					}

					//time for some computation !
					temp = strchr(work_buffer,' ');

					while(temp != NULL )
					{
						if(*(temp+1) != ' ' && *(temp+1) != '\0')
							param_count++;
						temp  = strchr(temp+1, ' ');

					}
					param_count+=2; //one for the program name + one for the first part of the string

					array = new char*[param_count];

					temp2 = strtok(work_buffer, " ");
					for(int i = 1; temp2 != NULL; i++)
					{
						array[i] = new char[strlen(temp2)+1];
						strncpy(array[i], temp2, strlen(temp2)+1);
						temp2 = strtok(NULL, " ");
					}
					std::cout << "\nNachricht an Client.";
					send(new_socket, prngd->work(param_count, array), 128, 0);


					//arrays loeschen
					for(int i = 1; i < param_count ; i++)
					{
						delete array[i];
					}
					delete array;
					memset(work_buffer, 0, BUFFER_SIZE);
					worker_busy = false;

					break;
				case SIGUSR2:
					//Server got the command to shutdown
					listen_thread_active = false;
					work_thread_active = false;
					break;
				default:
					//client closed connection, but server will still run and wait for further clients
					listen_thread_active = false;
					break;
			}
		}
	}
	close(create_socket);
	//wait for our listen_thread to be closed
	std::cout << "\nWarte auf beenden von Listener";
	WaitForListenerThreadToExit();
	std::cout << "\nTcp Server beendet.";
	active = false;
	//TODO: set a variable which is polled by Prngd_Server to signal the shutdown

}


